import blue
import uthread
import uicls
import uiutil
import uiconst
import base
import trinity
import log

class MonitorCore(uicls.Window):
    __guid__ = 'uicls.MonitorCore'
    default_windowID = 'monitor'

    def ApplyAttributes(self, attributes):
        uicls.Window.ApplyAttributes(self, attributes)
        self.SetCaption('Monitor')
        for each in ('focusText', 'moText', 'fpsText'):
            t = uicls.Label(name=each, parent=self.sr.content, align=uiconst.TOTOP, fontsize=10, autowidth=0, shadow=None)
            self.sr.Set(each, t)

        self.sr.theRest = uicls.Container(name='theRest', parent=self.sr.content, align=uiconst.TOALL, clipChildren=1, padding=(0, 8, 0, 0))
        self.sr.graphPar = uicls.Container(name='graphPar', parent=self.sr.theRest, align=uiconst.RELATIVE, pos=(0, 0, 128, 128), clipChildren=1)
        uicls.Frame(parent=self.sr.graphPar, color=(1.0, 1.0, 1.0, 0.25))
        self.sr.graph1 = uicls.Sprite(parent=self.sr.graphPar, align=uiconst.RELATIVE, pos=(0, 0, 128, 128), state=uiconst.UI_DISABLED)
        dev = trinity.device
        tex = dev.CreateTexture(128, 128, 1, trinity.TRIUSAGE_DYNAMIC, trinity.TRIFMT_A8R8G8B8, trinity.TRIPOOL_DEFAULT)
        self.sr.graph1.texture.AttachPixels(tex)
        self.sr.graph1.Invalidate()
        self.sr.graph2 = uicls.Sprite(parent=self.sr.graphPar, align=uiconst.RELATIVE, pos=(128, 0, 128, 128), state=uiconst.UI_DISABLED)
        tex2 = dev.CreateTexture(128, 128, 1, trinity.TRIUSAGE_DYNAMIC, trinity.TRIFMT_A8R8G8B8, trinity.TRIPOOL_DEFAULT)
        self.sr.graph2.texture.AttachPixels(tex2)
        self.sr.graph2.Invalidate()
        self.sr.graph1.DoPrepare = self.DoPrepare1
        self.sr.graph2.DoPrepare = self.DoPrepare2
        self.sr.graph1.texture.pixelBuffer.SetPixels(0, [])
        self.sr.graph2.texture.pixelBuffer.SetPixels(0, [])
        self.inactiveGraph = self.sr.graph1
        self.activeGraph = self.sr.graph2
        self.shift = 0
        self.fpsDict = {}
        self.startTime = blue.os.GetTime(1)
        self.fps = []
        self.avg = 0
        self.scale = settings.user.ui.Get('FPSScale', 1)
        self.showBars = settings.user.ui.Get('FPSSHowBars', 1)
        self.showAvg = settings.user.ui.Get('FPSShowAvg', 1)
        self.lastSec = 0
        self.buff = []
        self.lastHeight = 0
        self.sr.fpstimer = FpsTimer()
        self.sr.fpstimer.callback = self.AddFps
        self.sr.fpstimer.Start()
        self.sr.updateTimer = base.AutoTimer(100, self.UpdateData)



    def DoPrepare1(self, *args):
        self.DoPrepare(self.graph1)



    def DoPrepare2(self, *args):
        self.DoPrepare(self.graph2)



    def DoPrepare(self, graph):
        texture = trinity.TriTexture()
        texture.pixels = 'res:/uicore/texture/fill.dds'
        texture.translation.SetXYZ(0.0, 0.0, 0.0)
        texture.scaling.SetXYZ(1.0, 1.0, 1.0)
        graph.texture = texture
        rot = blue.os.CreateInstance('blue.Rot')
        dev = trinity.device
        tex = dev.CreateTexture(128, 128, 1, trinity.TRIUSAGE_DYNAMIC, trinity.TRIFMT_A8R8G8B8, trinity.TRIPOOL_DEFAULT)
        graph.texture.AttachPixels(tex)
        graph.texture.pixelBuffer.SetPixels(0, [])



    def UpdateData(self):
        if self.destroyed:
            return 
        mo = ('MO: %s' % self.GetTrace(uicore.uilib.mouseOver))
        if (self.sr.moText.text != mo):
            self.sr.moText.text = mo
        focusText = ''
        focus = uicore.registry.GetFocus()
        if focus:
            focusText += ('Focus: %s' % focus.name)
        else:
            focusText += 'Focus: None'
        active = uicore.registry.GetActive()
        if active:
            focusText += ('<br>Active: %s' % active.name)
        else:
            focusText += '<br>Active: None'
        if uicore.uilib.focus:
            focusText += ('<br>Uilib Focus: %s' % uicore.uilib.focus.name)
        else:
            focusText += '<br>Uilib Focus: None'
        if (self.sr.focusText.text != focusText):
            self.sr.focusText.text = focusText



    def GetTrace(self, item):
        trace = ''
        while item.parent:
            trace = (('/ ' + item.name) + trace)
            item = item.parent

        return trace



    def AddFps(self, fps):
        self.fps.append(fps)
        sec = (blue.os.GetTime() / 10000000)
        if ((sec > self.lastSec) and self.fps):
            self.lastSec = sec
            self.avg = (sum(self.fps) / len(self.fps))
            self.fps = []
            a = 1.0
        else:
            a = 0.5
        if (a == 1.0):
            self.fpsDict[(blue.os.GetTime(1) - self.startTime)] = self.avg
        if self.showBars:
            height = int((fps * self.scale))
            if (height >= self.lastHeight):
                for i in xrange(self.lastHeight, (height + 1)):
                    self.buff.append((self.shift,
                     (128 - i),
                     -2130706433))

            else:
                for i in xrange(height, (self.lastHeight + 1)):
                    self.buff.append((self.shift,
                     (128 - i),
                     -2130706433))

            if (a == 1.0):
                dotY = 125
                while (dotY > (128 - height)):
                    self.buff.append((self.shift,
                     dotY,
                     -2130706433))
                    dotY -= 3

            self.lastHeight = height
            self.shift += 1
            self.activeGraph.left -= 1
            self.inactiveGraph.left = (self.activeGraph.left - 128)
            self.activeGraph.texture.pixelBuffer.SetPixels(0, self.buff)
            if (self.activeGraph.left == 0):
                self.shift = 0
                self.buff = []
                preactive = self.activeGraph
                self.activeGraph = self.inactiveGraph
                self.inactiveGraph = preactive
                self.activeGraph.left = 128
        fpsText = ('FPS %d, Avg. FPS: %.1f' % (fps, self.avg))
        if (self.sr.fpsText.text != fpsText):
            self.sr.fpsText.text = fpsText




class FpsTimer(object):

    def __init__(self, maxlen = 200):
        self.len = maxlen
        self.fps = []
        self.min = 1000
        self.max = 0
        self.callback = None



    def Loop(weakSelf):
        last = 0L
        while 1:
            self = weakSelf()
            if ((not self) or self.stop):
                break
            now = blue.os.GetTime()
            dt = (now - last)
            if dt:
                last = now
                nowFps = (10000000.0 / float(dt))
                if self.callback:
                    self.callback(nowFps)
                else:
                    self.min = min(self.min, nowFps)
                    self.max = max(self.max, nowFps)
                    self.fps.append(nowFps)
                    if (len(self.fps) > (2 * self.len)):
                        self.fps = self.fps[-self.len:]
            del self
            blue.pyos.synchro.Yield()



    Loop = staticmethod(Loop)

    def Start(self):
        self.stop = False
        import weakref
        self.tasklet = uthread.new(self.Loop, weakref.ref(self))



    def Stop(self):
        self.stop = True



    def GetStats(self):
        return (self.fps[-self.len:],
         self.min,
         self.max)




